/*
This file is part of MMM.

MMM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

MMM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with MMM.  If not, see <http://www.gnu.org/licenses/>.
*
* @package    MMM
* @author     Andre Meixner
* @copyright  2017 High Performance Humanoid Technologies (H2T), Karlsruhe, Germany
*
*/

#ifndef __MMM_SENSORVISUALISATION_H_
#define __MMM_SENSORVISUALISATION_H_

#include <boost/shared_ptr.hpp>
#include <Inventor/nodes/SoSeparator.h>
#include <vector>

namespace MMM
{

class SensorVisualisation
{
public:
    SensorVisualisation(SoSeparator* sceneSep, SoSeparator* visualisationSep = nullptr) :
        sceneSep(sceneSep),
        visualisationSep(visualisationSep),
        visualisationDisplayed(true)
    {
        if (hasVisualisationSep()) sceneSep->addChild(this->visualisationSep);
    }

    void updateVisualisation(float timestep, float delta) {
        if (visualisationDisplayed) update(timestep, delta);
        lastTimestep = timestep;
        lastDelta = delta;
    }

    void updateVisualisation(float timestep) {
        if (visualisationDisplayed) update(timestep);
        lastTimestep = timestep;
    }

    virtual void displayVisualisation(bool display) {
        if (visualisationDisplayed != display) {
            if (visualisationSep != nullptr) {
                if (display) {
                    update(lastTimestep, lastDelta);
                    sceneSep->addChild(visualisationSep);
                } else {
                    if (visualisationSep->getRefCount() <= 1) visualisationSep->ref();
                    sceneSep->removeChild(visualisationSep);
                }
            }
            visualisationDisplayed = display;
        }
    }

    virtual std::string getType() = 0;

    virtual int getPriority() = 0;

protected:

    virtual void update(float timestep, float delta) = 0;
    virtual void update(float timestep) = 0;

    bool hasVisualisationSep() {
        return visualisationSep != nullptr;
    }

    void addChildVisualisationSep(SoSeparator* childSep) {
        if (hasVisualisationSep()) visualisationSep->addChild(childSep);
    }

    void removeChildVisualisationSep(int index) {
        if (hasVisualisationSep()) visualisationSep->removeChild(index);
    }

    SoNode* getChildVisualisationSep(int index) {
        if (hasVisualisationSep()) return visualisationSep->getChild(index);
        return nullptr;
    }

    void setVisualisationSep(SoSeparator* visualisationSep) {
        visualisationSep->ref();
        if (hasVisualisationSep() && visualisationDisplayed) sceneSep->removeChild(this->visualisationSep);
        else if (visualisationDisplayed) sceneSep->addChild(visualisationSep);
        this->visualisationSep = visualisationSep;
    }

    SoSeparator* getVisualisationSep() {
        return visualisationSep;
    }

    float lastTimestep;
    float lastDelta;
private:
    SoSeparator* sceneSep;
    SoSeparator* visualisationSep;
    bool visualisationDisplayed;
};

typedef boost::shared_ptr<SensorVisualisation> SensorVisualisationPtr;
typedef boost::shared_ptr<std::vector<SensorVisualisationPtr> > SensorVisualisationList;

}

#endif
